/*
 * @filename AuthServerSecurityConfiguration.java
 * @author barry
 * @version 0.0.1
 * @date 2020年1月14日
 */
package com.bnzj.cloud.auth.config;

import com.bnzj.cloud.auth.custom.CustomAccessTokenConverter;
import com.bnzj.cloud.auth.custom.CustomEndpointExceptionTranslator;
import com.bnzj.cloud.auth.extend.AuthServerLoginTypeHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import javax.annotation.Resource;
import javax.sql.DataSource;

/**
 * @author barry
 * @date 2020-01-14
 */
@Configuration
@EnableAuthorizationServer
public class AuthServerSecurityConfiguration extends AuthorizationServerConfigurerAdapter {

    @Resource
    private DataSource dataSource;

    @Autowired
    private AuthenticationManager authenticationManager;

    /**
     * 生成JTW token
     * @return
     */
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter converter = new CustomAccessTokenConverter();
        converter.setSigningKey("-----BEGIN RSA PRIVATE KEY-----\n" +
                "MIICXAIBAAKBgQCsPS1u1r7pl3VsEK4Tvc2NjNvXhaO2ACh+R889bMo3rz9PQQur\n" +
                "bj83pKfFDqcAbj/bhXbcQMG+Gs8WlUFmFNBVr651IL5h1gCrxfyivsQbWYbX5p4J\n" +
                "fk52rCMr2QJjnCvyFh1layHZ2gg5/cLQsMR8SqGTHaQmSLCHkoaVq7u8IQIDAQAB\n" +
                "AoGARSoH7YNkhI7igzOrg5frTBUtTr2GgRZNLHCPot3l0jiYVq4LDpsl3aVMDZCV\n" +
                "tVGQaQmOMmH6quk/EZV7/o8LHUTGcj6i1p2vKBqmAz9M9eUFE/eFctf+k6PAiqKc\n" +
                "kFa9HRSBukWne8SZw81qcxVxxw728dvzzahjP/n/mf9c/wUCQQDYjbZyrdK6QH86\n" +
                "9P+VhZHeqEBa+rerSMxY3KiCYfRDh8v+C5CNZXdvWVXafu3B/o/U4e7eSyReBomw\n" +
                "ybTlwdBrAkEAy5z+o0apRTsuUztAtJvhd0LGsuTyp8TzlI4nFywEHdLzJ47LNnQa\n" +
                "yD9P7VBQO4ZeYb+sKC4Qayf6vMR5q94YowJBALSIkA3S89bqZidUkK6qiA1D30L5\n" +
                "uZ1GN3Xtn13zI5wY3euQ4JXAfW2K4JQjNTuBaY9kO6t+oXbxpGCKCBFzHrkCQGFI\n" +
                "3L2EmIH0mdi4udzRkfOamzeEfpA8YSl8lh7TMBBT50viRSP6a4V8AqNfuUYHmHbZ\n" +
                "ztbP05ZvXrTspzm//0MCQHUcBARpGbzBnMI7j8xAjZJcrpmAhiMKjsix96sJPDjK\n" +
                "ocy7JgQCH1252bIPiaqO3wjCy+F31IClFNNaw3JQRCA=\n" +
                "-----END RSA PRIVATE KEY-----");
        converter.setVerifierKey("-----BEGIN PUBLIC KEY-----\n" +
                "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCsPS1u1r7pl3VsEK4Tvc2NjNvX\n" +
                "haO2ACh+R889bMo3rz9PQQurbj83pKfFDqcAbj/bhXbcQMG+Gs8WlUFmFNBVr651\n" +
                "IL5h1gCrxfyivsQbWYbX5p4Jfk52rCMr2QJjnCvyFh1layHZ2gg5/cLQsMR8SqGT\n" +
                "HaQmSLCHkoaVq7u8IQIDAQAB\n" +
                "-----END PUBLIC KEY-----");
        return converter;
    }
    
    /**
     * JWTtokenStore
     * @return
     */
    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    @Bean
    public CustomEndpointExceptionTranslator customEndpointExceptionTranslator(){
        return new CustomEndpointExceptionTranslator();
    }


    /**
     * 配置jwttokenStore
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.allowedTokenEndpointRequestMethods(HttpMethod.GET);
        endpoints.authenticationManager(authenticationManager);
        endpoints.exceptionTranslator(customEndpointExceptionTranslator());
        endpoints.tokenStore(tokenStore()).accessTokenConverter(jwtAccessTokenConverter());
    }

    @Autowired
    private AuthServerLoginTypeHandler authServerLoginTypeHandler;
    /**
     * springSecurity 授权表达式，访问tokenkey时需要经过认证
     * @param security
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.addTokenEndpointAuthenticationFilter(authServerLoginTypeHandler);
        security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()").allowFormAuthenticationForClients();
    }



    /**
     * 客户端一些配置
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //org.springframework.security.oauth2.provider.client.JdbcClientDetailsService
        ClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);
        //clients.jdbc()
        clients.withClientDetails(clientDetailsService);
    }

    /**
     * 客户端配置（给谁发令牌）
     * @param clients
     * @throws Exception
     */
    /*@Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory().withClient("internet_plus")
                .secret("internet_plus")
                //有效时间 2小时
                .accessTokenValiditySeconds(72000)
                //密码授权模式和刷新令牌
                .authorizedGrantTypes("refresh_token","password")
                .scopes( "all");
    }*/

}
